#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Gree.h>
#include <stdlib.h>
#define MAX_SER_CLIENTS 10

const char* ssid = "";
const char* password = "";
const char* mqttServer = "";

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
IPAddress ip;

WiFiServer server(80);

const uint16_t kIrLed = 4;
IRsend irsend(kIrLed);   

String data;
String reg[2*MAX_SER_CLIENTS] = {"","","","","","","","","","","","","","","","","","","",""};
int reg_index = 0; //用于往寄存器中加入内容的索引
int top = 0;       //用于将寄存器中内容处理的索引
int send_count = 0;

Ticker ticker;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);               // 启动串口通讯
  WiFi.mode(WIFI_STA);
  connectWifi();
  mqttClient.setServer(mqttServer, 1883);
  mqttClient.setCallback(receiveCallback);
  connectMQTTserver();
  ticker.attach_ms(50,sendCount);
  irsend.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (mqttClient.connected()) { // 如果开发板成功连接服务器
    mqttClient.loop();          // 处理信息以及心跳
  } 
  else {                      // 如果开发板未能成功连接服务器
    connectMQTTserver();        // 则尝试连接服务器
  }
    
  if (send_count == 5) {
    send();
    send_count = 0;    
  }
}

void sendCount(){
  send_count++;
}

void connectMQTTserver(){
  // 根据ESP8266的MAC地址生成客户端ID（避免与其它ESP8266的客户端ID重名）
  String clientId = "esp8266-" + WiFi.macAddress();
  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str())) { 
    Serial.println("MQTT Server Connected.");
    Serial.println("Server Address:");
    Serial.println(mqttServer);
    Serial.println("ClientId: ");
    Serial.println(clientId);
    subscribeTopic(); // 订阅指定主题
  } else {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(5000);
  }   
}

void receiveCallback(char* topic, byte* payload, unsigned int length) {
  char *code;
  Serial.print("Message Received [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    *code= (char)payload[i];
    code++;    
  }
  Serial.println("");
  Serial.print("Message Length(Bytes) ");
  Serial.println(length);
  if(reg[reg_index] != "") {
    delay(100);
  }
  reg[reg_index] = code; 
  reg_index = (reg_index+1) % (2*MAX_SER_CLIENTS);
}

void subscribeTopic(){
 
  // 建立订阅主题1。主题名称以Taichi-Maker-Sub为前缀，后面添加设备的MAC地址。
  // 这么做是为确保不同设备使用同一个MQTT服务器测试消息订阅时，所订阅的主题名称不同
  String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress();
  char subTopic[topicString.length() + 1];  
  strcpy(subTopic, topicString.c_str());
  
  // 建立订阅主题2
  String topicString2 = "Taichi-Maker-Sub2-" + WiFi.macAddress();
  char subTopic2[topicString2.length() + 1];  
  strcpy(subTopic2, topicString2.c_str());
  
  // 通过串口监视器输出是否成功订阅主题1以及订阅的主题1名称
  if(mqttClient.subscribe(subTopic)){
    Serial.println("Subscrib Topic:");
    Serial.println(subTopic);
  } else {
    Serial.print("Subscribe Fail...");
  }  
 
  // 通过串口监视器输出是否成功订阅主题2以及订阅的主题2名称
  if(mqttClient.subscribe(subTopic2)){
    Serial.println("Subscrib Topic:");
    Serial.println(subTopic2);
  } else {
    Serial.print("Subscribe Fail...");
  }    
}

void connectWifi(){
 WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("\n");
  server.begin();
  Serial.print(F("server.status :"));
  Serial.println(server.status());
  ip = WiFi.localIP();
  Serial.println(ip);
}

void send(){
  if(reg[top]!= "") {
    //
   long long code=atoll(reg[top].c_str());
    irsend.sendGree(code);
    delay(2000);
    reg[top] = "";
    top = (top+1) % (2*MAX_SER_CLIENTS);
  }
}
